package com.ocean.proxy.api.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.protobuf.InvalidProtocolBufferException;
import com.inveno.util.CollectionUtils;
import com.ocean.core.common.JsonUtils;
import com.ocean.core.common.UniversalUtils;
import com.ocean.core.common.http.HttpClient;
import com.ocean.core.common.http.HttpInvokeException;
import com.ocean.core.common.system.SystemContext;
import com.ocean.core.common.threadpool.AbstractInvokeResponse;
import com.ocean.core.common.threadpool.Parameter;
import com.ocean.core.common.threadpool.workthread.AsynAbstractTask;
import com.ocean.core.common.threadpool.workthread.AsynInvokeResponse;
import com.ocean.core.common.threadpool.workthread.Task.DataFormat;
import com.ocean.core.common.threadpool.workthread.Task.InvokeType;
import com.ocean.persist.api.proxy.AdPullException;
import com.ocean.persist.api.proxy.AdPullResponse;
import com.ocean.persist.api.proxy.adhub.AdHubAdPuller;
import com.ocean.persist.api.proxy.adhub.AdHubAdRequest;
import com.ocean.persist.api.proxy.adhub.AdHubAdResponse;
import com.ocean.persist.api.proxy.adhub.AdHubAdResponse.AdContentInfo;
import com.ocean.persist.api.proxy.adhub.AdHubAdResponse.AdContentSlot;
import com.ocean.persist.api.proxy.adhub.AdHubAdResponse.AdResponse;
import com.ocean.persist.api.proxy.adhub.AdHubAdResponse.DetectInfo;
import com.ocean.persist.api.proxy.adhub.AdHubAdResponse.ServerResponse;
import com.ocean.persist.api.proxy.adhub.AdHubAdResponse.SpaceInfo;
import com.ocean.persist.api.proxy.adhub.AdHubCommonInfo;
import com.ocean.persist.api.proxy.adhub.AdHubCommonInfo.DeviceInfo;
import com.ocean.persist.api.proxy.adhub.AdHubEnumType.AdpType;
import com.ocean.persist.api.proxy.adhub.AdHubEnumType.DeviceType;
import com.ocean.persist.api.proxy.adhub.AdHubEnumType.IspType;
import com.ocean.persist.api.proxy.adhub.AdHubEnumType.NetType;
import com.ocean.persist.api.proxy.adhub.AdHubEnumType.PlatformType;
import com.ocean.persist.api.proxy.adhub.AdHubEnumType.RenderType;
import com.ocean.persist.api.proxy.adhub.AdHubEnumType.ReqType;
import com.ocean.persist.api.proxy.adhub.AdHubEnumType.SrcType;
import com.ocean.persist.api.proxy.adhub.AdhubTemplate;
import com.ocean.persist.common.ProxyConstants;
import com.ocean.persist.model.proxy.DSPPosition;
import com.ocean.proxy.api.base.AbstractAdSupplier;
import com.ocean.proxy.api.base.AbstractAsynAdSupplier;
import com.ocean.proxy.serverdis.AdProxyAdhubTask;
import com.ocean.proxy.serverdis.TaskServerDispatcher;
import com.ocean.proxy.thrift.entity.AdContent;
import com.ocean.proxy.thrift.entity.AdImg;
import com.ocean.proxy.thrift.entity.AdMutiAction;
import com.ocean.proxy.thrift.entity.AdRecomReply;
import com.ocean.proxy.thrift.entity.AdRecomReq;
import com.ocean.proxy.thrift.entity.AdSpaceType;
import com.ocean.proxy.thrift.entity.AdUserInfo;
import com.ocean.proxy.thrift.entity.AdVid;
import com.ocean.proxy.thrift.entity.ExpectedMarketType;
import com.ocean.proxy.thrift.entity.UserAdSpaceAttri;
@Component(value="adHubAdSupplier")
public class AdHubAdSupplier   extends AbstractAsynAdSupplier{
    @Autowired
	private AdHubAdPuller adHubAdPuller;
	protected static final Map<String, IspType> mobiles = new HashMap<String, IspType>(5);
	static{
		mobiles.put("CMCC", IspType.ISP_CN_MOBILE);
		mobiles.put("CUCC", IspType.ISP_CN_UNICOM);
		mobiles.put("CTCC", IspType.ISP_CN_TEL);

	}
	private static final Map<String, NetType> ctype = new HashMap<String, NetType>();
	static{
		ctype.put(NETWORK_2G, NetType.NET_2G);
		ctype.put(NETWORK_3G, NetType.NET_3G);
		ctype.put(NETWORK_4G, NetType.NET_4G);
		ctype.put(NETWORK_WIFI, NetType.NET_WIFI);
	}
	public AdRecomReply invoke(InvokeAttribute attribute) throws AdPullException {
		
		AdRecomReq adreq = attribute.getAdreq();
		DSPPosition positionInfo = attribute.getDspPosition();
		// 参数转换
		AdHubAdRequest.SdkRequest params = parseParams(adreq, positionInfo);
		
		//AdHubAdResponse.ServerResponse response = (AdHubAdResponse.ServerResponse) adHubAdPuller.api(params,adreq.getHash(),String.valueOf(adreq.getUserAdSpaceAttri().getAdSpaceId()));
		AdHubAdResponse.ServerResponse response = (AdHubAdResponse.ServerResponse) invoke(params,ServerResponse.class,adreq.getHash(),String.valueOf(adreq.getUserAdSpaceAttri().getAdSpaceId()),"joinDSP:adhub");
		
		return parseResult(response,adreq.getUserAdSpaceAttri());
	}
/*	public  AdPullResponse invoke(Parameter params,String ... exts){
		//init task
		AsynInvokeResponse data=asynRequest(params, exts[0]);
		AdHubAdResponse.ServerResponse ss=null;
		if(data!=null){
			ss=(AdHubAdResponse.ServerResponse)data.getData();
			logger.info("joinDSP:adhub {} reply result:{}",exts,ss==null?data.getData():UniversalUtils.replaceBlank(ss.toString()));	
		}
		
        
		
		// 0 无错误 1 竞价出错/拒绝竞价  2无效的请求
		return ss;
	}*/

	public AsynAbstractTask packageTask(Parameter params,String hashCode){
		AdProxyAdhubTask task=new AdProxyAdhubTask();
		//heard
		Map<String, String> headers = new HashMap<String, String>(2);
		headers.put("Content-Type", "application/x-protobuf");
		headers.put("x-protobuf-version", "v2_9");
		task.setHeaders(headers);
		

		AdHubAdRequest.SdkRequest param = (AdHubAdRequest.SdkRequest) params;
		logger.info("joinDSP:adhub {} request param:{}",hashCode,UniversalUtils.replaceBlank(param.toString()));
		task.setParam(param);
		task.setDataFormat(DataFormat.DATA_FORMAT_STREAM);
		task.setInvokeType(InvokeType.INVOKE_TYPE_POST);
		task.setHashCode(hashCode);
		task.setUrl(SystemContext.getDynamicPropertyHandler().get(ProxyConstants.ADHUB_URL));
		
		return task;
	}
	private AdRecomReply parseResult(AdHubAdResponse.ServerResponse response,UserAdSpaceAttri    attri)
			throws AdPullException {
		
		if(response == null||CollectionUtils.isEmpty(response.getSpaceInfoList())){
			return null;
		}
		if(response.getStatus()==1){
			
			throw new AdPullException("ad request error,joinDSP:adhub return error code:"+response.getErrcode()+",error massage:"+response.getErrmsg());
		}
		SpaceInfo spaceInfo=response.getSpaceInfo(0);
		if(CollectionUtils.isEmpty(spaceInfo.getAdResponseList())){
			return null;
		}
		AdResponse adResponse=spaceInfo.getAdResponse(0);

		//判断广告位类型是否一致
/*		if(validateAdSpaceType(attri.getSpaceType(),spaceInfo.getAdpType())){
			throw new AdPullException("ad space type is not mapping!");
		}*/
		//广告类型校验
		if(!attri.getExpectedMarketTypes().contains(ExpectedMarketType.VIDEO)&&AdpType.ADP_IVIDEO==spaceInfo.getAdpType()){
			throw new AdPullException("ad  type is not mapping!");
		}
		// 可用素材类型, bit位组合, 1:图片; 2:图文; 4:文字链; 8:html; 16:视频; 32:vas视频; 64:json; 128:landing; 256: preload
		if(spaceInfo.getContentType()!=8&&attri.getH5type()==1){
			throw new AdPullException("return  ad is not h5,we need h5 ad!");
		}else if(spaceInfo.getContentType()==8&&attri.getH5type()==2){
			throw new AdPullException("return  ad is  h5,we need not h5 ad!");
		}

		AdContentInfo adContentResp=adResponse.getContentInfo(0);
		AdContent content = new AdContent();
		// 类型
		AdMutiAction action = new AdMutiAction();

		//------------------BEGIN 常规设置-------------------

		String title = defTitle;
		String marketTile=defTitle;

		// 内容类型1表示链接推广,2表示应用推广,3未使用 4表示电话推广
		action.setType(ACTION_WEB);
		//------------------END 常规设置---------------------

		
		
		logger.info("joinDSP:adhub  adTypeL{},ad size:{},template:{}",adContentResp.getRenderType(),adContentResp.getSize(),adContentResp.getTemplate());
		List<AdImg> imgs = new ArrayList<AdImg>();
		if(adContentResp.getRenderType()==RenderType.RENDER_JSON){
			AdhubTemplate temp=JsonUtils.toBean(adContentResp.getTemplate(), AdhubTemplate.class);
			for(String url:temp.getImages()){//
				AdImg img=new AdImg();
				img.setSrc(url);
				imgs.add(img);
			}
			if(imgs.isEmpty()&&StringUtils.isNotEmpty(temp.getImage())){//防止图片未取到
				AdImg img=new AdImg();
				img.setSrc(temp.getImage());
				imgs.add(img);
			}
			if(StringUtils.isNotEmpty(temp.getHeadline())){
				title=temp.getHeadline();
			}
			if(CollectionUtils.isNotEmpty(temp.getTexts())){
				marketTile=temp.getTexts().get(0);
			}
			if(marketTile.equals(defTitle)&&StringUtils.isNotEmpty(temp.getBody())){
				marketTile=temp.getBody();
			}
		}else{
			for(AdContentSlot slot:adContentResp.getAdcontentSlotList()){
				
				AdImg img=new AdImg();
				img.setSrc(slot.getContent());
				imgs.add(img);

			}
		}

		// 返回对象
		AdRecomReply recomReply = new AdRecomReply();
		recomReply.setStatus(status);
		
		Map<String, List<String>> map = new HashMap<String, List<String>>();
		// 点击监测
		List<String> clickL=new ArrayList<String>();
		List<String> viewL=new ArrayList<String>();
		
		if(adContentResp.getRenderType()==RenderType.RENDER_H5&&StringUtils.isNotEmpty(adContentResp.getTemplate())){
			content.setIsHtmlAd(true);
			content.setHtmlSnippet(adContentResp.getTemplate());
		}
		
		if(adResponse.getInteractInfo()!=null){
			if(StringUtils.isNotEmpty(adResponse.getInteractInfo().getHubDetectInfo().getViewUrl())){
				viewL.add(adResponse.getInteractInfo().getHubDetectInfo().getViewUrl());
			}
			if(StringUtils.isNotEmpty(adResponse.getInteractInfo().getHubDetectInfo().getClickUrl())){
				clickL.add(adResponse.getInteractInfo().getHubDetectInfo().getClickUrl());
			}
			
			for(DetectInfo thirdDet:adResponse.getInteractInfo().getThirdpartInfoList()){
				viewL.add(thirdDet.getViewUrl());
				clickL.add(thirdDet.getClickUrl());
				
			}
			if(CollectionUtils.isNotEmpty(adResponse.getInteractInfo().getImpTrackersList())&&CollectionUtils.isEmpty(viewL)){
				viewL.addAll(adResponse.getInteractInfo().getImpTrackersList());
			}
			if(CollectionUtils.isNotEmpty(adResponse.getInteractInfo().getClickTrackersList())&&CollectionUtils.isEmpty(clickL)){
				clickL.addAll(adResponse.getInteractInfo().getClickTrackersList());
			}
			
			// 落地页
			String link =adResponse.getInteractInfo().getLandingPageUrl();
			
/*			if(StringUtils.isEmpty(link)){
				throw new AdPullException("adhub landing link url is empty!");
			}*/
			if(StringUtils.isNotEmpty(link)){
				action.setLinkurl(link);
				content.setLinkurl(link);
			}

			//视频广告
			
			if(AdpType.ADP_IVIDEO==spaceInfo.getAdpType()&&CollectionUtils.isNotEmpty(spaceInfo.getPreloadCtxList())){//视频广告
				
				AdContentInfo videoAd=spaceInfo.getPreloadCtx(0);
				AdVid adVid=new AdVid();
				adVid.setSrc(link);
				adVid.setDuration(spaceInfo.getMinTime());
				content.setAdVid(adVid);
				action.setType(ACTION_VIDEO);

				for(AdContentSlot slot:videoAd.getAdcontentSlotList()){
					AdImg img=new AdImg();
					img.setSrc(slot.getContent());
					imgs.add(img);

				}
				
			}
			
		}

		content.setMarketTitle(marketTile);
		content.setGuideTitle(title);
		content.setImglist(imgs);
		map.put(CLICK, clickL);
		map.put(SHOW, viewL);
		content.setThirdReportLinks(map);
		action.setGuideTitle(title);
		content.setMutiAction(Collections.singletonList(action));
		recomReply.setAd_content(content);
		
		return recomReply;
	}
	private boolean validateAdSpaceType(AdSpaceType   adSpaceType,AdpType adpType){
		if(adpType==null){
			return true;
		}
		switch(adSpaceType){
		     case BANNER:
		    	 if(adpType==AdpType.ADP_BANNER){
		    		 
		    		 return true;

		    	 }
		     case OPENING:
		    	 if(adpType==AdpType.ADP_LOADING){
		    		 
		    		 return true;

		    	 }
		     case INTERSTITIAL:
		    	 if(adpType==AdpType.ADP_TABLE){
		    		 
		    		 return true;

		    	 } 
		     case INFOFLOW:
		    	 if(adpType==AdpType.ADP_NATIVE){
		    		 
		    		 return true;

		    	 }
		     default:
		    	 if(adpType==AdpType.ADP_UNKNOWN){
		    		 return true;
		    	 }else{
		    		 return false;
		    	 }
		    		 
		    	 
		}

	}
	private AdHubAdRequest.SdkRequest parseParams(AdRecomReq adreq, 
			DSPPosition positionInfo) throws AdPullException {
		if(StringUtils.isEmpty(positionInfo.getText1())){
			throw new AdPullException("appid is empty!");
		}
		DeviceInfo.Builder deviceBuilder=DeviceInfo.newBuilder();
	    deviceBuilder.setSdkUID(adreq.getOgin_name());
		AdUserInfo userInfo=adreq.getUserinfo();
		String osCode = userInfo.getOs();
		// 如果是ios
	    String os = "Android ";
	    if(OS_IOS.equals(osCode)){
			// ios 必填信息
	    	deviceBuilder.setIdfa(userInfo.getIdfa());
			os="Ios ";
			deviceBuilder.setPlatform(PlatformType.PLATFORM_IOS);
	    }else if(OS_ANDROID.equals(osCode)){
	    	deviceBuilder.setImei(userInfo.getImei());
			deviceBuilder.setPlatform(PlatformType.PLATFORM_ANDROID);
		}
	    deviceBuilder.setOs(os+this.convOSVersion(userInfo.getOsversion()));
		if(StringUtils.isNotEmpty(userInfo.getMac())){
			deviceBuilder.setMac(this.converMac(userInfo.getMac()));
		}
		
		deviceBuilder.setDevType(DeviceType.DEVICE_PHONE);
		if(StringUtils.isNotEmpty(userInfo.getBrand_name())){
			deviceBuilder.setBrand(userInfo.getBrand_name());
		}
		if(StringUtils.isNotEmpty(userInfo.getPhonemodel())){
			deviceBuilder.setModel(userInfo.getPhonemodel());
		}
		if(StringUtils.isNotEmpty(userInfo.getAdid())){
			deviceBuilder.setAndroidID(userInfo.getAdid());
		}
		deviceBuilder.setResolution(userInfo.getDevice_width()+"_"+userInfo.getDevice_height());
		if(StringUtils.isNotEmpty(userInfo.getDensity())){
			deviceBuilder.setDensity(userInfo.getDensity());
		}
		//userInfo
		AdHubCommonInfo.UserEnvInfo.Builder userInfoBuilder=AdHubCommonInfo.UserEnvInfo.newBuilder();
		if(StringUtils.isNotEmpty(userInfo.getClient_ip())){
			userInfoBuilder.setIp(userInfo.getClient_ip());
		}
		IspType isp=mobiles.get(userInfo.getMobile());
		if(isp==null){
			userInfoBuilder.setIsp(IspType.ISP_OTHER);
		}else{
			userInfoBuilder.setIsp(isp);
		}
		NetType netType=ctype.get(adreq.getNet());
		userInfoBuilder.setNet(netType==null?NetType.NET_WIFI:netType);
		userInfoBuilder.setUserAgent(userInfo.getUa());
		if(StringUtils.isNotEmpty(userInfo.getLat())&&StringUtils.isNotEmpty(userInfo.getLon())){
			AdHubCommonInfo.Geo geo=AdHubCommonInfo.Geo.newBuilder()
					                                   .setLongitude(userInfo.getLon())
					                                   .setLatitude(userInfo.getLat()).build();
			userInfoBuilder.setGeo(geo);
		}
		
		//ad request info
		AdHubAdRequest.AdReqInfo adReq=AdHubAdRequest.AdReqInfo.newBuilder().setSpaceID(positionInfo.getPos()).build();
		
		AdHubAdRequest.SdkRequest.Builder sdkRequestBuilder=AdHubAdRequest.SdkRequest.newBuilder();
		sdkRequestBuilder.setVersion("0.1.0")
		                 .setSrcType(SrcType.SRC_APP)
		                 .setReqType(ReqType.REQ_AD)
		                 .setTimeStamp(System.currentTimeMillis())
		                 .setAppid(positionInfo.getText1());
	    sdkRequestBuilder.setDevInfo(deviceBuilder.build());
	    sdkRequestBuilder.setEnvInfo(userInfoBuilder.build());
	    sdkRequestBuilder.addAdReqInfo(adReq);
		return sdkRequestBuilder.build();
	}


	public AdHubAdPuller getAdHubAdPuller() {
		return adHubAdPuller;
	}

	public void setAdHubAdPuller(AdHubAdPuller adHubAdPuller) {
		this.adHubAdPuller = adHubAdPuller;
	}


}
